#ifndef _PROC_H_
#define _PROC_H_

#include "base.h"
#include "ipc.h"
#include "page.h"

/************************************************/
/*                                              */
/*          definition of context 				*/
/*                                              */
/************************************************/

/* task_context only includes stack info and memory info */
/* common register are stored in stack */
struct task_context{
	//reg_t eip;
	//reg_t eflags;
	
	//reg_t eax;
	//reg_t ecx;
	//reg_t edx;
	//reg_t ebx;

	//reg_t esp3;
	//reg_t ebp;
	//reg_t esi;
	//reg_t edi;

	//sel_t cs;
	//sel_t ds;
	//sel_t ss3;
	//sel_t es;
	//sel_t gs;
	//sel_t fs;
	//sel_t ss0;
	reg_t esp0;
	reg_t cr3;
	
	reg_t esp3;
};

#define CONTEXT_LEN sizeof(struct task_context)

/************************************************************/
/*                                                          */
/*       miscellaneous flags and definition of process 		*/
/*                                                          */
/************************************************************/

#define RUN			0
#define READY		1
#define SUSPEND		2
#define SLEEP		3
#define DEAD		4

#define PROC_IDLE	0
//#define PROC_PM		1
//#define PROC_TTY	2

#define PROC_SERVER_MAX		(PROC_IDLE + 1)
#define PROC_USR_NUM		256	

#define PROC_NUM			(PROC_SERVER_MAX + PROC_USR_NUM)


/* all server processes run with the highest level -- PRIV0 */
#define PRIV0			0	

#define PRIV1			1
#define PRIV2			2
#define PRIV3			3
#define PRIV4			4
#define PRIV5			5
#define PRIV6			6
#define PRIV7			7

#define PRIV8			8			/* suspend processes queue */

#define PRIV_MAX		PRIV8

#define SERVER_PRIV			PRIV0
#define USER_PRIV_START		PRIV1
#define USER_PRIV_END		PRIV7
#define SUSPEND_PRIV		PRIV8

#define DEFAULT_TICK		10

#define is_proc_in_user_priv(priv)		((priv >= USER_PRIV_START) && (priv <= USER_PRIV_END))
#define is_proc_in_server_priv(priv)	(priv == SERVER_PRIV)

struct proc{
	uint_32 pid;
	uint_32 priv;

	uint_32 ticks;
	uint_32 sleep_ticks;

	uint_32 status;

	char name[16];

	struct task_context context;
	
	struct page page;

	struct mm_frame mm;

	struct message *msg;

	/* relation with other processes */
	struct proc *child;
#if 0
	struct proc *brother;
	struct proc *father;
#endif

	/* for message schedule */
	struct proc *ipc_with;

	/* for schedule */
	struct proc *next;
};

#define set_proc_priv(proc,priv)			proc->priv = priv
#define set_proc_ticks(proc,ticks)		proc->ticks = ticks
#define set_proc_status(proc,status)		proc->status = status


/* server processes are in the process-tree , too. they are in the highest privilege */
EXTERN struct proc proc[PROC_SERVER_MAX + PROC_USR_NUM] ;				/* this is server processes, used for initializing the servers */
EXTERN struct proc *proc_queue_h[PRIV_MAX] ;		/* different privilege process queues, used for scheduling */
EXTERN struct proc *proc_queue_t[PRIV_MAX] ;		/* different privilege process queues, used for scheduling */
EXTERN struct proc *proc_suspend_queue;				/* suspend processes queue */
EXTERN struct proc *cur_proc;

int proc_en_suspend_queue(struct proc *proc_p);
int proc_de_suspend_queue(struct proc *proc_p);
int proc_en_ready_queue(struct proc *proc_p);
int proc_de_ready_queue(struct proc *de_proc);
int proc_free(struct proc **del_proc);
struct proc* proc_new(void);
int do_switch(struct proc *pick_proc);
int sched(struct proc *candidate_proc);

int msg_check(struct message *msg);
int send(struct message *msg);
int recv(struct message *msg);
int notify(struct message *msg);

#endif
